package com.fivestar.finance.library.widget.slidedatetimepicker;

import java.util.Calendar;
import java.util.Date;

import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.text.format.DateUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.TextView;

import com.fivestar.finance.library.R;


/**
 * <p>The {@code DialogFragment} that contains the {@link SlidingTabLayout}
 * and {@link CustomViewPager}.</p>
 * <p>
 * <p>The {@code CustomViewPager} contains the {@link DateFragment}.</p>
 * <p>
 * <p>This {@code DialogFragment} is managed by {@link SlideDatePicker}.</p>
 *
 * @author derek
 */
public class SlideDateDialogFragment extends DialogFragment implements DateFragment.DateChangedListener {
    public static final String TAG_SLIDE_DATE_DIALOG_FRAGMENT = "tagSlideDateDialogFragment";

    private static SlideDateTimeListener mListener;

    private Context mContext;

    private TextView titleDate;

    private CustomDatePicker mDatePicker;

    private Button mOkButton;

    private Button mCancelButton;

    private Date mInitialDate;

    private Date mMinDate;

    private Date mMaxDate;

    private Calendar mCalendar;

    private int mDateFlags = DateUtils.FORMAT_SHOW_WEEKDAY | DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_ALL;

    public SlideDateDialogFragment() {
        // Required empty public constructor
    }

    /**
     * <p>Return a new instance of {@code SlideDateDialogFragment} with its bundle
     * filled with the incoming arguments.</p>
     * <p>
     * <p>Called by {@link SlideDatePicker#show()}.</p>
     *
     * @param listener
     * @param initialDate
     * @param minDate
     * @param maxDate
     * @return
     */
    public static SlideDateDialogFragment newInstance(SlideDateTimeListener listener, Date initialDate, Date minDate,
                                                      Date maxDate) {
        mListener = listener;

        // Create a new instance of SlideDateDialogFragment
        SlideDateDialogFragment dialogFragment = new SlideDateDialogFragment();

        // Store the arguments and attach the bundle to the fragment
        Bundle bundle = new Bundle();
        bundle.putSerializable("initialDate", initialDate);
        bundle.putSerializable("minDate", minDate);
        bundle.putSerializable("maxDate", maxDate);

        dialogFragment.setArguments(bundle);

        // Return the fragment with its bundle
        return dialogFragment;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        mContext = activity;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setRetainInstance(true);

        unpackBundle();

        mCalendar = Calendar.getInstance();
        mCalendar.setTime(mInitialDate);
        setStyle(DialogFragment.STYLE_NO_TITLE, android.R.style.Theme_Holo_Light_Dialog_NoActionBar);

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.slide_date_picker, container);

        setupViews(view);
        initButtons();


        // block keyboard popping up on touch
        mDatePicker.setDescendantFocusability(DatePicker.FOCUS_BLOCK_DESCENDANTS);
        mDatePicker.init(
                mCalendar.get(Calendar.YEAR),
                mCalendar.get(Calendar.MONTH),
                mCalendar.get(Calendar.DAY_OF_MONTH),
                new DatePicker.OnDateChangedListener() {

                    @Override
                    public void onDateChanged(DatePicker view, int year,
                                              int monthOfYear, int dayOfMonth) {
                        SlideDateDialogFragment.this.onDateChanged(year, monthOfYear, dayOfMonth);
                    }
                });

        if (mMinDate != null)
            mDatePicker.setMinDate(mMinDate.getTime());

        if (mMaxDate != null)
            mDatePicker.setMaxDate(mMaxDate.getTime());

        return view;
    }

    @Override
    public void onDestroyView() {
        // Workaround for a bug in the compatibility library where calling
        // setRetainInstance(true) does not retain the instance across
        // orientation changes.
        if (getDialog() != null && getRetainInstance()) {
            getDialog().setDismissMessage(null);
        }

        super.onDestroyView();
    }

    private void unpackBundle() {
        Bundle args = getArguments();

        mInitialDate = (Date) args.getSerializable("initialDate");
        mMinDate = (Date) args.getSerializable("minDate");
        mMaxDate = (Date) args.getSerializable("maxDate");

    }

    private void setupViews(View v) {
        titleDate = (TextView) v.findViewById(R.id.tv_title_date);
        mDatePicker = (CustomDatePicker) v.findViewById(R.id.datePicker);
        mOkButton = (Button) v.findViewById(R.id.okButton);
        mCancelButton = (Button) v.findViewById(R.id.cancelButton);
    }

    private void initButtons() {
        mOkButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mListener == null) {
                    throw new NullPointerException("Listener no longer exists for mOkButton");
                }

                mListener.onDateTimeSet(new Date(mCalendar.getTimeInMillis()));

                dismiss();
            }
        });

        mCancelButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mListener == null) {
                    throw new NullPointerException("Listener no longer exists for mCancelButton");
                }

                mListener.onDateTimeCancel();

                dismiss();
            }
        });
    }


    /**
     * <p>The callback used by the DatePicker to update {@code mCalendar} as
     * the user changes the date. Each time this is called, we also update
     * the text on the date tab to reflect the date the user has currenly
     * selected.</p>
     * <p>
     * <p>Implements the {@link DateFragment.DateChangedListener}
     * interface.</p>
     */
    @Override
    public void onDateChanged(int year, int month, int day) {
        mCalendar.set(year, month, day);
        titleDate.setText(DateUtils.formatDateTime(mContext, mCalendar.getTimeInMillis(), mDateFlags));
    }


    /**
     * <p>Called when the user clicks outside the dialog or presses the <b>Back</b>
     * button.</p>
     * <p>
     * <p><b>Note:</b> Actual <b>Cancel</b> button clicks are handled by {@code mCancelButton}'s
     * event handler.</p>
     */
    @Override
    public void onCancel(DialogInterface dialog) {
        super.onCancel(dialog);

        if (mListener == null) {
            throw new NullPointerException("Listener no longer exists in onCancel()");
        }

        mListener.onDateTimeCancel();
    }
}
